import socket
import subprocess
import struct
#连接目标
host = 'localhost'
port = 8080

#建立socket对象，基于对tcp的抽象，无需关注细节
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

#绑定，建立通信连接
s.bind((host,port))

#监听，确定连接的数量
s.listen(5)

#等待连接，并阻塞程序，知道收到客户端的连接请求
#accept返回一个元组-->元组中一个socket对象，一个客户端的IP、端口对象
print('start connecting')
#建立链接循环，用于同时链接多个客户端

#计数器，对链接的客户端进行计数
counter = 0
while True:
    conn_sock, conn_addr = s.accept()
    if conn_sock:
        counter += 1
        print('客户端个数：', counter)
    print(conn_addr)

    while True:   
        # 接受客户端发送的请求
        try:
            cmd = conn_sock.recv(1024)
            if not cmd:
                break
            print('客户端数据：', cmd.decode('utf-8'))
           
            
            obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            
            stdout, stderr = obj.communicate()
            #把命令的结果返回客户端
            #第一步：制作固定长度的报头
            total_size = len(stdout) + len(stderr)
            header = struct.pack('i', total_size)
            
            #第二部：把报头发给客户端
            conn_sock.send(header)
            #第三步：发送真实数据
            conn_sock.send(stdout)
            conn_sock.send(stderr)

        except ConnectionResetError:
            print('客户端断开连接')
            break

    # 关闭传输消息的socket
    conn_sock.close()
# 关闭计算机连接的socket
s.close()